﻿Imports System.IO
Imports System.Text

Module Common

    Friend AppPath As String = Application.StartupPath

    Friend reloadWeaponKeyCode As Integer = 17 'W
    Friend itemFastMoveKeyCode As Integer = 29 'Ctrl
    Friend highlightKeyCode As Integer = 42 'SHIFT
    Friend pickupItemKeyCode As Integer = 34 'G
    Friend windowScrollKeyCode As Integer = -2 'ALT
    Friend toggleCombatKeyCode As Integer = 0
    Friend hideInterfaceKeyCode As Integer = 45 ' X

    Private savedValues As Dictionary(Of String, Color) = New Dictionary(Of String, Color)

    Private gameDebugSection() As String = {
            "[debug]",
            "mode=environment",
            "output_map_data_info=1",
            "show_load_info=1",
            "show_script_messages=1",
            "show_tile_num=1" & vbNewLine
    }

    Friend Sub MainCheck()
        Dim arguments As String() = System.Environment.GetCommandLineArgs()
        For Each Arg As String In arguments
            If (Arg.StartsWith("-install ")) Then
                Dim isMerge = False
                Dim isDelete = False
                If Arg.ElementAt(9) = "+"c Then isDelete = True

                Dim bakddrawIni As String = AppPath & "\" & "ddraw.ini.bak"
                If File.Exists(bakddrawIni) Then
                    ddrawIni = File.ReadAllLines(AppPath & "\ddraw.ini", Encoding.Default).ToList
                    Merge(bakddrawIni, True)

                    File.WriteAllLines(AppPath & "\ddraw.ini", ddrawIni.ToArray, Encoding.Default)
                    If isDelete Then File.Delete(bakddrawIni)
                    isMerge = True
                End If

                Dim bakModsIni As String = AppPath & "\" & "sfall-mods.ini.bak" ' скопированный предыдуший
                If File.Exists(bakModsIni) Then
                    Dim iniFolder As String = AppPath & "\" & Arg.Substring(10).Trim("""") ' переданный путь к ini файлам 
                    iniFolder += "\sfall-mods.ini"
                    If File.Exists(iniFolder) = False Then
                        iniFolder = AppPath & "\sfall-mods.ini"
                    End If

                    ddrawIni = File.ReadAllLines(iniFolder, Encoding.Default).ToList
                    Merge(bakModsIni, False)

                    File.WriteAllLines(iniFolder, ddrawIni.ToArray, Encoding.Default)
                    If isDelete Then File.Delete(bakModsIni)
                    isMerge = True

                End If
                If (isMerge) Then
                    MessageBox.Show("Настройки в ddraw.ini и sfall-mods.ini были успешно сохранены.", "SF-Configurator")
                End If
                Application.Exit()
                System.Environment.Exit(0)
            End If
        Next
    End Sub

    Friend Sub DatDesc()
        Dim path As String = AppPath & "\dat.unp"
        Dim datFiles = Directory.GetFiles(AppPath, "*.dat", SearchOption.TopDirectoryOnly).ToList
        If Directory.Exists(AppPath + "\mods\") Then
            datFiles.AddRange(Directory.GetFiles(AppPath + "\mods\", "*.dat", SearchOption.TopDirectoryOnly).ToList)
        End If

        If datFiles.Count Then
            File.Delete(path)
            File.WriteAllBytes(path, My.Resources.dat2)
            File.SetAttributes(path, FileAttributes.Hidden)
        End If

        For Each datFile In datFiles
            Shell(AppPath & "\dat.unp x """ & datFile & """ desc.id", AppWinStyle.Hide, True, 1000)

            Dim descID As String() = Nothing
            path = AppPath & "\desc.id"
            If File.Exists(path) Then
                descID = File.ReadAllLines(path)
            End If

            Dim z As Integer = datFile.LastIndexOf("\") + 1
            Dim item As ListViewItem
            If descID Is Nothing Then
                item = New ListViewItem(New String() {datFile.Substring(z), "<no description>"})
            Else
                item = New ListViewItem(New String() {datFile.Substring(z), descID(1)})
            End If
            item.ToolTipText = datFile
            MainForm.ListView1.Items.Add(item)

            File.Delete(path)
        Next
    End Sub

    Friend Sub InputDesc()
        Dim Name As String = MainForm.ListView1.FocusedItem.Text
        Dim desc As String = InputBox("Введите описание для " & Name, , MainForm.ListView1.Items(
                                      MainForm.ListView1.FocusedItem.Index).SubItems(1).Text)

        If desc <> String.Empty AndAlso desc <> MainForm.ListView1.FocusedItem.SubItems(1).Text Then
            MainForm.ListView1.FocusedItem.SubItems(1).Text = desc
            Dim desc_dat As String() = {Name, desc}
            Name = """" & MainForm.ListView1.FocusedItem.ToolTipText & """"
            File.WriteAllLines(AppPath & "\desc.id", desc_dat)
            Shell(AppPath & "\dat.unp d " & Name & " desc.id", AppWinStyle.Hide, True, 1000)
            Shell(AppPath & "\dat.unp a " & Name & " desc.id", AppWinStyle.Hide, True, 1000)
            File.Delete(AppPath & "\desc.id")
            Shell(AppPath & "\dat.unp k " & Name, AppWinStyle.Hide, True, 1000)
        End If
    End Sub

    Friend Sub SetSelectListResolution()
        Dim res As String = MainForm.nudResWidth.Value.ToString + " x " + MainForm.nudResHeight.Value.ToString

        For i As Integer = 0 To MainForm.lstSfallResolution.Items.Count - 1
            If MainForm.lstSfallResolution.Items(i).ToString.Contains(res) Then
                MainForm.lstSfallResolution.SelectedIndex = i
                Exit For
            End If
        Next
    End Sub

    Friend Sub SetIniResolution_HRP(width As String, height As String)
        ConfigFuncs.SetIniValue("[MAIN]", "SCR_WIDTH", width, f2ResIni)
        ConfigFuncs.SetIniValue("[MAIN]", "SCR_HEIGHT", height, f2ResIni)
    End Sub

    Friend Sub CheckExeCRC(ByVal game_exe As String)
        Dim crcVal As String = CRC.GetHexCRC(AppPath & "\" & game_exe)
        Dim crcValues() As String = MainForm.tbExtraCRC.Text.Split(",")

        For Each crc As String In crcValues
            If crc.Trim.ToUpper = "0X" & crcVal OrElse crc.Trim.ToUpper = crcVal Then
                Exit Sub ' есть в списке
            End If
        Next

        If MainForm.tbExtraCRC.Text.Length > 0 Then
            MainForm.tbExtraCRC.Text &= ", 0x" & crcVal 'заносим в тексбох
        Else
            MainForm.tbExtraCRC.Text = "0x" & crcVal
        End If
        SetIniCRC() 'записать изменения в буффер
    End Sub

    Friend Sub SetIniCRC()
        If ConfigFuncs.SetConfigIniValue("ExtraCRC", MainForm.tbExtraCRC.Text) Then
            MainForm.tbExtraCRC.Enabled = True
        End If
    End Sub

    Friend Sub SetDebugSection()
        If cfgGameData.Count AndAlso ConfigFuncs.GetIniSectionLineIndex("[Debug]", cfgGameData) = -1 Then
            cfgGameData.InsertRange(0, gameDebugSection) ' вставить раздел
            cfgSave = True
        End If
    End Sub

    Friend Sub Merge(ByVal iniPath As String, ByVal addModIni As Boolean)
        If File.Exists(iniPath) = False Then Exit Sub

        Dim fromINI() As String = File.ReadAllLines(iniPath, Encoding.Default)
        Dim section As String = Nothing

        For Each line As String In fromINI
            line = line.TrimStart()
            If line.Length = 0 OrElse line.StartsWith(";") Then Continue For

            If (line.StartsWith("[")) Then
                Dim n = line.IndexOf("]")
                If (n <> -1) Then section = line.Substring(0, n + 1)
                Continue For
            End If
            If section Is Nothing Then Continue For

            Dim key = ConfigFuncs.GetKeyName(line)

            If key <> String.Empty Then
                Dim value = ConfigFuncs.GetKeyValue(line)
                If value <> String.Empty Then
                    ConfigFuncs.MergeSetConfigIniValue(section, key, value)
                End If
            End If
        Next

        If (addModIni) Then
            Dim valueStr As String = ConfigFuncs.GetIniValue("[Main]", "ModifiedIni", fromINI)
            If valueStr IsNot Nothing Then
                Dim n As Integer = ConfigFuncs.GetSectionLineIndex("[Main]") + 1
                ddrawIni.Insert(n, "ModifiedIni=" & valueStr)
                ddrawIni.Insert(n + 1, "")
            End If
        End If
    End Sub

    Friend Function GetDecDXKeyCode(ByRef scode As String) As Byte
        If (scode Is Nothing) Then Return 0

        If scode.StartsWith("0x") Then
            scode = "&H" & scode.Remove(0, 2)
        End If

        Dim code As Byte
        Return If(Byte.TryParse(scode, code), code, 0)
    End Function

    Friend Function MaxMin(ByVal value As Integer, ByVal min As Integer, ByVal max As Integer) As Integer
        If (value > max) Then
            Return max
        ElseIf (value < min) Then
            Return min
        End If
        Return value
    End Function

    ''' <summary>
    ''' Creates a relative path from one file or folder to another.
    ''' </summary>
    ''' <param name="fromPath">Contains the directory that defines the start of the relative path.</param>
    ''' <param name="toPath">Contains the path that defines the endpoint of the relative path.</param>
    ''' <returns>The relative path from the start directory to the end path or <c>toPath</c> if the paths are not related.</returns>
    Friend Function MakeRelativePath(ByRef fromPath As String, ByVal toPath As String) As String
        If Not File.Exists(toPath) Then
            Dim n = toPath.LastIndexOf(Path.DirectorySeparatorChar)
            toPath = toPath.Substring(0, n)
        End If

        Dim fromUri = New Uri(fromPath + Path.DirectorySeparatorChar)
        Dim toUri = New Uri(toPath)

        If (fromUri.Scheme <> toUri.Scheme) Then Return toPath ' path can't be made relative.

        Dim relativeUri = fromUri.MakeRelativeUri(toUri)
        Dim relativePath = Uri.UnescapeDataString(relativeUri.ToString())

        If (toUri.Scheme.Equals("file", StringComparison.InvariantCultureIgnoreCase)) Then
            relativePath = relativePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar)
        End If

        Return relativePath
    End Function

    'Friend Function MakeRelativePath(ByVal pathA As String, ByVal pathB As String) As String
    '    If (pathA.Equals(pathB, StringComparison.OrdinalIgnoreCase)) Then Return String.Empty

    '    Dim absParts() = pathA.Split(Path.DirectorySeparatorChar)
    '    Dim relParts() = pathB.Split(Path.DirectorySeparatorChar)

    '    ' Get the shortest of the two paths
    '    Dim len = Math.Min(absParts.Length, relParts.Length) 'If(absParts.Length < relParts.Length, absParts.Length, relParts.Length)

    '    Dim lastCommonRoot = -1 ' Use to determine where in the loop we exited

    '    ' Find common root
    '    For index = 0 To len - 1
    '        If absParts(index).Equals(relParts(index), StringComparison.OrdinalIgnoreCase) Then
    '            lastCommonRoot = index
    '        Else
    '            Exit For
    '        End If
    '    Next

    '    ' If we didn't find a common prefix then throw
    '    If (lastCommonRoot = -1) Then Throw New ArgumentException("The path of the two files doesn't have any common base.")
    '    lastCommonRoot += 1

    '    ' Build up the relative path
    '    Dim relativePath = New StringBuilder()

    '    ' Add on the ..
    '    For index = lastCommonRoot To relParts.Length - 1
    '        relativePath.Append("..")
    '        relativePath.Append(Path.DirectorySeparatorChar)
    '    Next

    '    ' Add on the folders
    '    For index = lastCommonRoot To absParts.Length - 2
    '        relativePath.Append(absParts(index))
    '        relativePath.Append(Path.DirectorySeparatorChar)
    '    Next
    '    relativePath.Append(absParts(absParts.Length - 1))

    '    Return relativePath.ToString
    'End Function

    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

    Friend Function SetColor(ByVal optionName As String, ByVal valColor As Color) As Color
        Dim savedValue As Color

        If GetSavedValue(optionName, savedValue) = False Then
            SetSavedValue(optionName, valColor)
            Return Color.MediumVioletRed
        End If

        If valColor = savedValue Then
            Return Color.MediumVioletRed
        End If

        Return savedValue
    End Function

    Private Sub SetSavedValue(ByVal optionName As String, ByVal valColor As Color)
        If savedValues.ContainsKey(optionName) Then Return

        savedValues.Add(optionName, valColor)
    End Sub

    Private Function GetSavedValue(ByVal optionName As String, ByRef outColor As Color) As Boolean
        If savedValues.ContainsKey(optionName) = False Then Return False

        outColor = savedValues.Item([optionName])
        Return True
    End Function

End Module
